//Eli Elder
//gainCard
//makefile needs this
//unittest1: unittest1.c dominion.o rngs.o
//	gss -o unittest1 -g unittest1.c dominion.o rngs.o $(CFLAGS)


#include "dominion.h"
#include "dominion_helpers.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h> 
#include <assert.h>
#include <math.h>
#include "rngs.h"

//set PRINTOUT to 0 to remove printfs out
#define PRINTOUT 1
#define ASSERTIVE 0
#define PRINTOUTASSERT 1
int checkGainCard(int supplyPos, struct gameState *afterGainState, int toFlag, int player){
    struct gameState beforeGainState;
    int returnVal;
    int deckNum;
    int handNum;
    int discardNum;
    int supplyNum;
    //copy so we can test if the gain card worked how we think it should
    memcpy(&beforeGainState, afterGainState, sizeof(struct gameState));
    
    //set the card counts so we can make sure they are correct later
    deckNum = beforeGainState.deckCount[player];
    handNum = beforeGainState.handCount[player];
    discardNum = beforeGainState.discardCount[player];
    supplyNum = beforeGainState.deckCount[player];
    
    
    //do the gain card
    returnVal = gainCard(supplyPos, afterGainState, toFlag, player);
    
#if (PRINTOUT == 1)
    //check that the supply coint is good
    if(supplyCount(supplyPos, &beforeGainState) < 1){
	printf("Error supplyPos is under one\n");
    }
#endif
    
    //what we test depends on the flag, need to make the "before" look like the after then assert it
    if(toFlag == 1){ //going to deck from supply pos
	beforeGainState.deckCount[player]++;
	beforeGainState.deck[player][beforeGainState.deckCount[player] - 1] = supplyPos;
    } else if (toFlag == 2){ //going to hand from supplypos
	beforeGainState.handCount[player]++;
	beforeGainState.hand[player][beforeGainState.handCount[player] - 1] = supplyPos;
    } else{ //which I feel should be toFlag 0, but thats what they said going to discard from supplypos
	beforeGainState.discardCount[player]++;
	beforeGainState.discard[player][beforeGainState.discardCount[player] - 1] = supplyPos;
    }
    
    
    
    //all of them have the supply one go down
    beforeGainState.supplyCount[supplyPos]--;
    
#if (PRINTOUT == 1)   
    //if the full deck counts arent the same gain and discard messed up
    if(fullDeckCount(player, supplyPos,&beforeGainState) < fullDeckCount(player, supplyPos, afterGainState)){
	printf("The gaincard has more cards than the test\n");
    } else if(fullDeckCount(player, supplyPos, &beforeGainState) > fullDeckCount(player, supplyPos, afterGainState)){
	printf("The gaincard has less cards than the test\n");
    }
    //check the hand cards
    if(beforeGainState.handCount[player] < afterGainState->handCount[player]){
	printf("The gaincard has more hand cards than the test\n");
    } else if(beforeGainState.handCount[player] > afterGainState->handCount[player]){
	printf("The gaincard has less hand cards than the test\n");
    }
    
    //check the supply count of the card
    
    if(toFlag == 1){ //going to deck from supply pos
        //check the deckcount is plus 1
        if(afterGainState->deckCount[player] == (deckNum + 1)){
            printf("The deck count was correctly incremented\n");
        }else{
            printf("The deck count wasnt incremented\n");
        }
    } else if (toFlag == 2){ //going to hand from supplypos
        //check the handcount is plus 1
        if(afterGainState->handCount[player] == (handNum + 1)){
            printf("The hand count was correctly incremented\n");
        }else{
            printf("The hand count wasnt incremented\n");
        }
    } else{ //which I feel should be toFlag 0, but thats what they said going to discard from
        //check the discard count is plus 1
        if(afterGainState->discardCount[player] == (discardNum + 1)){
            printf("The discard count was correctly incremented\n");
        }else{
            printf("The discard count wasnt incremented\n");
        }
    }
#endif
#if (ASSERTIVE == 1)
    //tests that we returned 0 (basically we had more than 0 supplyPos and it is used                                                                                              
    assert(returnVal == 0);
    
    //assert that the after gainCard state is the same as we expect it to be with the "before" that we made like the after                                                         
    assert(memcmp(&beforeGainState, afterGainState, sizeof(struct gameState)) == 0);
#endif
#if (PRINTOUTASSERT == 1)
    //only do this printout if you do assertive too
    //print off the where to
    if(toFlag == 2){
	printf("The deck correctly gained the card "); 
    }else if (toFlag == 1){
	printf("The hand correctly gained the card ");
    }else{
	printf("The discard pile correctly gained the ");
    }
    //print off the card
    switch(supplyPos){
    case adventurer: printf("adventurer\n"); break;
    case copper: printf("copper\n"); break;
    case feast: printf("feast\n"); break;
    case gardens: printf("gardens\n"); break;
    case curse: printf("curse\n"); break;
    case remodel: printf("remodel\n"); break;
    case smithy: printf("smithy\n"); break;
    case village: printf("village\n"); break;
    case baron: printf("baron\n"); break;
    case salvager: printf("salvager\n"); break;
    }
    
#endif
    
    return 0;
}

int main() {
    int i;
    int numPlayers = 1;
    int toWhere;
    int cardSupply;
    int numDeck = 10;
    int numDiscard = 10;
    int numHand = 6;
    int initialized;
    struct gameState theGameState;
    int kingCards[10] = {adventurer, copper, feast, gardens, curse, remodel, smithy, village, baron, salvager};
    
    //this helps setup the random tests
    SelectStream(2);
    PutSeed(3);
    
    //small fixed tests that loop through EVERYTHING!!!!!!
    for(cardSupply = 0; cardSupply < 10; cardSupply++){
	for(toWhere = 0; toWhere < 3; toWhere++){
	    //setup and initialize the state (should do in random?)
	    memset(&theGameState, 23, sizeof(struct gameState));
	    initialized = initializeGame(1, kingCards, 1, &theGameState);
	    
	    //assign the deck, hand, and discard
	    theGameState.deckCount[numPlayers] = numDeck;
	    theGameState.discardCount[numPlayers] = numDiscard;
	    theGameState.handCount[numPlayers] = numHand;
	    
	    //mem set the deck, hand, and discard
	    memset(theGameState.deck[numPlayers], kingCards[cardSupply], sizeof(int) * numDeck);
	    memset(theGameState.discard[numPlayers], kingCards[cardSupply], sizeof(int) * numDiscard);
	    //memset(theGameState.hand[numPlayers], 0, sizeof(int) * numHand);
	    //setup the supply count
	    memset(theGameState.supplyCount, 0, sizeof(int) * (treasure_map + 1));
	    int handItems[numHand];
	    for(i = 0; i < numHand; i++){
		handItems[i] = kingCards[cardSupply];
		theGameState.supplyCount[kingCards[cardSupply]]++;
	    }
	    //setup the hand card count
	    theGameState.handCount[numPlayers] = numHand;
	    
	    
	    memcpy(theGameState.hand[numPlayers], handItems, sizeof(int) * numHand);
	    
#if (PRINTOUT == 1)
	    if(toWhere == 2){
		printf("Trying to deck in the hand the card "); 
	    }else if (toWhere == 1){
		printf("Trying to gain in the hand the card ");
	    }else{
		printf("Trying to discard in the hand the card ");
	    }
	    //print off the card
	    switch(kingCards[cardSupply]){
	    case adventurer: printf("adventurer\n"); break;
	    case copper: printf("copper\n"); break;
	    case feast: printf("feast\n"); break;
	    case gardens: printf("gardens\n"); break;
	    case curse: printf("curse\n"); break;
	    case remodel: printf("remodel\n"); break;
	    case smithy: printf("smithy\n"); break;
	    case village: printf("village\n"); break;
	    case baron: printf("baron\n"); break;
	    case salvager: printf("salvager\n"); break;
	    }
#endif
	    //do the test
	    checkGainCard(kingCards[cardSupply], &theGameState, toWhere, 1);
	}
    }
    
    return 0;
}
